﻿#pragma once

#include "geom_curve.h"

namespace CAGD
{

/**
 * @brief 曲面基类.
 *
 */
class GeomSurface : public GeomBase
{
  public:
    /**
     * @brief 取值函数.
     * @return
     * @param u
     * @param v
     * @see
     */
    BPnt Value(double u, double v) const;

    /**
     * @brief 取值函数.
     * @return
     * @param p
     * @see
     */
    BPnt Value(const BPnt2d &p) const;

    /**
     * @brief 法向函数.
     * @return
     * @param u
     * @param v
     * @see
     */
    BVec Normal(double u, double v) const;

    /**
     * @brief 法向函数.
     * @return
     * @param p
     * @see
     */
    BVec Normal(const BPnt2d &p) const;

    /**
     * @brief 返回类型.
     * @return
     * @see
     */
    GeomType Type() const override;

    /**
     * @brief 曲面三角化.
     * @return
     * @param surface
     * @param nu
     * @param nv
     * @see
     */
    static Handle(TriangleMesh) Triangulate(Handle(GeomSurface) surface, int nu, int nv);

    /**
     * @brief 曲面点均匀采样.
     * @return
     * @param surface
     * @param nu
     * @param nv
     * @see
     */
    static std::vector<BPnt> UniformPointSample(Handle(GeomSurface) surface, int nu, int nv);

    /**
     * @brief 曲面法线均匀采样.
     * @return
     * @param surface
     * @param nu
     * @param nv
     * @see
     */
    static std::vector<BVec> UniformNormalSample(Handle(GeomSurface) surface, int nu, int nv);

    /**
     * @brief 曲面 u 等参线.
     * @return
     * @param surface
     * @param u
     * @param size
     * @see
     */
    static std::vector<BPnt> IsoU(Handle(GeomSurface) surface, double u, int size);

    /**
     * @brief 曲面 v 等参线.
     * @return
     * @param surface
     * @param v
     * @param size
     * @see
     */
    static std::vector<BPnt> IsoV(Handle(GeomSurface) surface, double v, int size);

    /**
     * @brief 获得参数范围.
     * @param U1
     * @param U2
     * @param V1
     * @param V2
     * @see
     */
    virtual void Bounds(double &U1, double &U2, double &V1, double &V2) const = 0;

    /**
     * @brief 获得 0 阶导数.
     * @param u
     * @param v
     * @param P
     * @see
     */
    virtual void D0(double u, double v, BPnt &P) const = 0;

    /**
     * @brief 获得 1 阶导数.
     * @param u
     * @param v
     * @param P
     * @param DU
     * @param DV
     * @see
     */
    virtual void D1(double u, double v, BPnt &P, BVec &DU, BVec &DV) const = 0;

    /**
     * @brief 获得 2 阶导数.
     * @param u
     * @param v
     * @param P
     * @param DU
     * @param DV
     * @param DUU
     * @param DUV
     * @param DVV
     * @see
     */
    virtual void D2(double u, double v, BPnt &P, BVec &DU, BVec &DV, BVec &DUU, BVec &DVV, BVec &DUV) const = 0;

    /**
     * @brief 获得 N 阶导数信息.
     * @param N
     * @param u
     * @param v
     * @param V
     * @see
     */
    virtual void DN(int N, double u, double v, std::vector<std::vector<BPnt>> &V) const = 0;

    /**
     * @brief 获得 U 等参线节点.
     * @return
     * @see
     */
    virtual std::vector<double> IsoUKnots() const = 0;

    /**
     * @brief 获得 V 等参线节点.
     * @return
     * @see
     */
    virtual std::vector<double> IsoVKnots() const = 0;

    /**
     * @brief 获得 U 等参线数量.
     * @return
     * @see
     */
    virtual int NbIsoU() const = 0;

    /**
     * @brief 获得 V 等参线数量.
     * @return
     * @see
     */
    virtual int NbIsoV() const = 0;

    /**
     * @brief 获得控制点引用.
     * @return
     * @see
     */
    virtual std::vector<BPnt *> MakeReference() = 0;
};

} // namespace CAGD
